home *** CD-ROM | disk | FTP | other *** search
- Date: Tue, 5 Apr 94 15:59:08 PDT
- From: hyc@hanauma.jpl.nasa.gov (Howard Chu)
- Message-Id: <9404052259.AA09371@hanauma.jpl.nasa.gov>
- To: mint@atari.archive.umich.edu
- Subject: Screendump to MacPaint file for MiNT 1.10 + Psigintr
-
- Well, I needed something to dump a screen to a MacPaint file, and I couldn't
- find anything like that, let alone working under MiNT, thus this program.
- The screen rotation code is pretty slow; I'm working on a more efficient one
- but it works, so what the heck.
-
- Hope someone else finds this useful... -- Howard
-
- /*
- * scrdump - Dump a monochrome screen in MacPaint format. Requires MiNT 1.10
- * plus Psigintr extension. I wrote this program because I've seen no other
- * code that will dump a screen to a file when running under MiNT.
- *
- * The program doesn't put itself into the background, but it ought to.
- * Dump files are named "ScreenXX.MAC" with two hex digits "XX". The program
- * exits after dumping 256 images. If the environment variable SCRDUMPS exists
- * and is set to a GEMDOS-format pathname, dumps will be created in that
- * directory, otherwise they will be in the current working directory.
- *
- * The MacPaint format isn't exactly the greatest format in the world. It's
- * a fixed size, 576 horizontal by 720 vertical. The only reason I used it
- * is because I needed to get some screen dumps to a doc-writer who was using
- * a Mac, and this is the simplest Mac format I had docs for. To get a better
- * fit, I rotate the ST screen 90 degrees before dumping it to disk. For
- * screens larger than 720x576, only the upper left corner gets dumped.
- *
- * Not the best-written stuff in the world, but it works...
- *
- * -- Howard Chu, howard@lloyd.com 4-5-94
- * (also at hyc@hanauma.jpl.nasa.gov, but phasing that out.)
- */
-
- #include <mintbind.h>
- #include <unistd.h>
- #include <signal.h>
- #include <linea.h>
-
- int quit;
-
- void sigit (int sig) {
- if (sig != SIGHUP)
- quit = 1;
- }
-
- /*
- * Once again, a strange problem - how do you get a signal from an interrupt-
- * time routine into a MiNT process. Using Psigintr directly doesn't work here
- * because the ALT-Help vector isn't at a long-word aligned address, and it's
- * invoked as a subroutine, not an exception. Perhaps Psigintr should be
- * changed to take an address instead of a vector number, with another argument
- * telling whether to return with RTE or RTS... ?
- *
- * Anyway, my solution here is to set the ALT-Help vector to point to a
- * routine that invokes an unused trap. Psigintr is called with that trap
- * vector, and so the desired signal gets delivered... What a kludge.
- */
-
- #define Prt_cnt *(short *)0x4eeL
- #define Scr_dump *(long *)0x502L
- #define TRAP0VEC 0x20
-
- void trapper () {
- if (Prt_cnt == 0)
- Prt_cnt = -1;
- __asm__("trap #0");
- }
-
- long oldprt;
-
- void installer () {
- oldprt = Scr_dump;
- Scr_dump = (long)trapper;
- }
-
- void remover() {
- Scr_dump = oldprt;
- }
-
- const char digx[]="0123456789ABCDEF";
- char file[]="Screen00.MAC";
-
- /* MacPaint dimensions */
-
- #define M_X_MAX 576
- #define M_Y_MAX 720
- #define MAC_BUF ((M_X_MAX*M_Y_MAX>>3)+512)
-
- main() {
- int i, j;
- int snum;
- int xmax, ymax; /* max dimension, unrotated */
- int xlen;
-
- int fd;
- char *scr;
- char *wd, *pbuf;
- char *pt1, *pt2, *pt3, *pt4;
- char c, m1, m2;
-
- /* Go to specified dump directory */
-
- wd = (char *)getenv("SCRDUMPS");
- if (wd) {
- if (wd[1] == ':') {
- Dsetdrv((wd[0] & 0x1f)-1);
- wd += 2;
- }
- Dsetpath(wd);
- }
-
- scr = (char *)Logbase();
-
- /* Yeah, I know Line-A isn't supposed to be used any more, but it
- * still works on TT and Falcon, and there's no where else to find
- * the Bytes_Per_Line value...
- */
-
- linea0();
- xmax = V_X_MAX;
- if (xmax > M_Y_MAX)
- xmax = M_Y_MAX;
- ymax = V_Y_MAX;
- if (ymax > M_X_MAX)
- ymax = M_X_MAX;
- xlen = V_BYTES_LIN;
-
- wd = malloc(MAC_BUF); /* MacPaint rez + header */
- bzero(wd, MAC_BUF); /* zero the buffer */
- wd += 512; /* Skip over the header */
- pbuf = malloc((ymax>>3)+1); /* 1 PackBits line */
-
- #if BORDERS==1
- /* Draw 2-pixel borders if image is smaller than MacPaint size */
-
- if (ymax < M_X_MAX) {
- pt1 = wd + (ymax>>3);
- j = xmax+2;
- if (j > M_Y_MAX) j = M_Y_MAX;
- for (i=0; i<j; i++) {
- *pt1 = 0xc0;
- pt1 += (M_X_MAX>>3);
- }
- }
-
- if (xmax < M_Y_MAX-1) {
- pt1 = wd + xmax*(M_X_MAX>>3);
- for (i=0; i<ymax>>3; i++)
- *pt1++ = 0xff;
- pt1 += (M_X_MAX-ymax) >> 3;
- for (i=0; i<ymax>>3; i++)
- *pt1++ = 0xff;
- }
- #endif
-
- /* Use trap 0 vector to signal us */
-
- signal(SIGHUP, sigit);
- signal(SIGINT, sigit);
- signal(SIGQUIT, sigit);
- signal(SIGTERM, sigit);
-
- Psigintr(TRAP0VEC, SIGHUP);
- Supexec(installer);
-
- for(snum=0;snum<256;snum++) {
-
- /* Set file name */
-
- file[7] = digx[snum & 0x0f];
- file[6] = digx[snum >> 4];
-
- /* Wait for ALT-Help signal */
-
- Pause();
- if (quit)
- break;
-
- /* Open output file, write header */
-
- fd = Fcreate(file, 0);
- if (fd < 0)
- continue;
-
- Fwrite(fd, 512, wd-512);
-
- /* Rotate image 90 degrees */
-
- pt1=scr + (xmax>>3)-1; /* Far right src column */
- pt2=wd + ((M_X_MAX*(xmax-1)+ymax)>>3)-1;
- /* lower right corner */
- for (i=0, m1=1; i<xmax; i++) {
- pt3 = pt1; /* input */
- m2 = 1;
- for (j=0, c=0; j<ymax; j++) {
- if (*pt3 & m1)
- c |= m2;
- pt3 += xlen;
- if (m2 < 0) {
- m2 = 1;
- *pt2-- = c;
- c = 0;
- } else {
- m2 += m2;
- }
-
- }
- pt2 -= ((M_X_MAX-ymax)>>3);
- if (m1 < 0) { /* signed char */
- m1 = 1;
- pt1--;
- } else {
- m1 += m1;
- }
- }
-
- /* Write output in PackBits format */
-
- pt1 = wd;
- #if PACKBITS==1
- for (i=0; i<M_Y_MAX; i++) { /* For each line */
- m1 = 0; /* No repeats */
- m2 = *pt1+1; /* Previous char */
- pt3 = pt1; /* beginning of literal */
- pt4 = 0; /* beginning of run */
- pt2 = pbuf;
- for (j=0; j<M_X_MAX>>3; j++) {
- if (*pt1 == m2) {
- if (pt4) { /* Accumulate repeats */
- m1++;
- } else if (j<((M_X_MAX>>3)-1) && pt1[1] == m2) {
- pt4 = pt1-1; /* Initialize repeats */
- m1 = 3;
- ++j;
- ++pt1;
- if (pt3 < pt4) { /* flush literals */
- *pt2++ = pt4-pt3-1;
- for (;pt3 < pt4;)
- *pt2++ = *pt3++;
- }
- }
- pt1++;
- } else {
- if (m1) { /* End of run, how many? */
- --m1;
- *pt2++ = -m1;
- *pt2++ = m2;
- pt3 = pt1;
- pt4 = 0;
- m1 = 0;
- }
- m2 = *pt1++; /* set prev char */
- }
- }
-
- /* Dump end of line */
-
- if (m1) { /* finish repeats */
- --m1;
- *pt2++ = -m1;
- *pt2++ = m2;
- } else if (pt3 < pt1) { /* finish literals */
- *pt2++ = pt1-pt3-1;
- for(;pt3 < pt1;)
- *pt2++ = *pt3++;
- }
- Fwrite(fd, pt2 - pbuf, pbuf);
- }
- #else
- /* Dump it straight, no repeat-suppression */
-
- c = (M_X_MAX>>3)-1;
- for (i=0; i<M_Y_MAX; i++) {
- Fwrite(fd, 1, &c);
- Fwrite(fd, c+1, pt1);
- pt1 += c+1;
- }
- #endif
- Fclose(fd);
- }
- Supexec(remover);
- }
-